/**
 * 入住记录数据模型类
 * 
 * 这个类用来表示一条客人的入住记录，记录了客人入住酒店的完整信息
 * 包括入住时间、退房时间、费用等重要信息
 * 
 * 在酒店管理系统中，这个类的作用：
 * 1. 记录当前正在入住的客人信息（存储在checkin.txt文件中）
 * 2. 记录已经结账的历史入住信息（存储在history.txt文件中）
 * 3. 用于计算房费、统计入住率等业务功能
 * 
 * 与其他类的关系：
 * - Guest类：记录客人的基本信息
 * - Room类：记录房间的基本信息
 * - CheckIn类：记录客人在特定房间的入住过程
 * - Reservation类：记录预定信息
 * 
 * 数据流程：预定(Reservation) -> 入住(CheckIn) -> 结账(移到History)
 */
public class CheckIn {
    // ==================== 成员变量定义 ====================
    // 这些变量记录了一次完整入住过程的所有关键信息

    private String guestId; // 客人ID，关联到Guest表，用于识别是哪位客人
    private String guestName; // 客人姓名，冗余存储，方便显示（避免每次都查Guest表）
    private String roomNumber; // 房间号，关联到Room表，记录客人住在哪个房间
    private String checkInDate; // 入住日期，格式：yyyy-MM-dd（如：2025-05-20）
    private String checkOutDate; // 退房日期，格式：yyyy-MM-dd（如：2025-05-23）
    private double totalAmount; // 总费用，根据房间价格和入住天数计算得出
    private String status; // 入住状态：已入住、已结账

    /**
     * 构造方法 - 创建一条新的入住记录
     * 
     * 当客人办理入住手续时，系统会创建一个CheckIn对象来记录这次入住
     * 所有的参数都是必需的，确保入住记录的完整性
     * 
     * 调用示例：
     * CheckIn checkIn = new CheckIn("G123", "张三", "101", "2025-05-20",
     * "2025-05-23", 600.0, "已入住");
     * 
     * @param guestId      客人ID - 必须是已存在的客人ID
     * @param guestName    客人姓名 - 用于显示，应与Guest表中的姓名一致
     * @param roomNumber   房间号 - 必须是有效的房间号
     * @param checkInDate  入住日期 - 格式：yyyy-MM-dd
     * @param checkOutDate 预计退房日期 - 格式：yyyy-MM-dd
     * @param totalAmount  总金额 - 房间价格 × 入住天数
     * @param status       入住状态 - "已入住"或"已结账"
     */
    public CheckIn(String guestId, String guestName, String roomNumber, String checkInDate,
            String checkOutDate, double totalAmount, String status) {
        // 使用this关键字为成员变量赋值
        // this.变量名 = 参数名; 这是标准的构造方法写法
        this.guestId = guestId;
        this.guestName = guestName;
        this.roomNumber = roomNumber;
        this.checkInDate = checkInDate;
        this.checkOutDate = checkOutDate;
        this.totalAmount = totalAmount;
        this.status = status;
    }

    // ==================== Getter方法区域 ====================
    // 这些方法用于获取入住记录的各项信息
    // 在酒店管理系统中，这些信息会显示在各种界面上

    /**
     * 获取客人ID
     * 
     * 客人ID是连接入住记录和客人信息的桥梁
     * 通过这个ID可以查询到客人的详细信息
     * 
     * @return 客人的唯一标识ID
     */
    public String getGuestId() {
        return guestId;
    }

    /**
     * 获取客人姓名
     * 
     * 这里存储客人姓名是为了方便显示，避免每次都要通过guestId去查询Guest表
     * 这种做法叫做"数据冗余"，用空间换时间，提高查询效率
     * 
     * @return 客人的姓名
     */
    public String getGuestName() {
        return guestName;
    }

    /**
     * 获取房间号
     * 
     * 房间号用于标识客人住在哪个房间
     * 在前台管理中，经常需要根据房间号查询入住情况
     * 
     * @return 房间号（如：101、203、301等）
     */
    public String getRoomNumber() {
        return roomNumber;
    }

    /**
     * 获取入住日期
     * 
     * 入住日期是客人正式入住酒店的日期
     * 用于计算入住天数和房费
     * 
     * @return 入住日期，格式：yyyy-MM-dd
     */
    public String getCheckInDate() {
        return checkInDate;
    }

    /**
     * 获取退房日期
     * 
     * 对于正在入住的客人，这是预计退房日期
     * 对于已结账的客人，这是实际退房日期
     * 
     * @return 退房日期，格式：yyyy-MM-dd
     */
    public String getCheckOutDate() {
        return checkOutDate;
    }

    /**
     * 获取总金额
     * 
     * 总金额 = 房间单价 × 入住天数
     * 这个金额在客人结账时收取
     * 
     * @return 总费用（单位：元）
     */
    public double getTotalAmount() {
        return totalAmount;
    }

    /**
     * 获取入住状态
     * 
     * 状态说明：
     * - "已入住"：客人正在酒店，还没有结账
     * - "已结账"：客人已经退房并结账，记录移到历史记录中
     * 
     * @return 入住状态
     */
    public String getStatus() {
        return status;
    }

    // ==================== Setter方法区域 ====================
    // 这些方法用于修改入住记录的信息
    // 在实际业务中，某些信息可能需要更新（如延长退房日期、修改状态等）

    /**
     * 设置客人ID
     * 
     * 注意：在实际应用中，客人ID通常不应该修改
     * 这里提供setter主要是为了数据模型的完整性
     * 
     * @param guestId 新的客人ID
     */
    public void setGuestId(String guestId) {
        this.guestId = guestId;
    }

    /**
     * 设置客人姓名
     * 
     * 如果客人的姓名在Guest表中被修改了，
     * 这里也需要同步更新以保持数据一致性
     * 
     * @param guestName 新的客人姓名
     */
    public void setGuestName(String guestName) {
        this.guestName = guestName;
    }

    /**
     * 设置房间号
     * 
     * 在特殊情况下可能需要为客人更换房间
     * 比如房间设施故障、客人要求升级等
     * 
     * @param roomNumber 新的房间号
     */
    public void setRoomNumber(String roomNumber) {
        this.roomNumber = roomNumber;
    }

    /**
     * 设置入住日期
     * 
     * 通常入住日期不会修改，但在数据纠错时可能需要
     * 
     * @param checkInDate 新的入住日期
     */
    public void setCheckInDate(String checkInDate) {
        this.checkInDate = checkInDate;
    }

    /**
     * 设置退房日期
     * 
     * 这是最常用的setter方法之一
     * 用途：
     * 1. 客人续住时，延长退房日期
     * 2. 客人提前退房时，修改退房日期
     * 3. 结账时，设置实际退房日期
     * 
     * @param checkOutDate 新的退房日期
     */
    public void setCheckOutDate(String checkOutDate) {
        this.checkOutDate = checkOutDate;
    }

    /**
     * 设置总金额
     * 
     * 当退房日期改变时，总金额也需要重新计算
     * 或者在有折扣、优惠时需要调整金额
     * 
     * @param totalAmount 新的总金额
     */
    public void setTotalAmount(double totalAmount) {
        this.totalAmount = totalAmount;
    }

    /**
     * 设置入住状态
     * 
     * 这是一个重要的方法，用于改变入住记录的状态
     * 主要用途：
     * 1. 客人结账时，将状态从"已入住"改为"已结账"
     * 2. 取消入住时，可能需要修改状态
     * 
     * @param status 新的入住状态
     */
    public void setStatus(String status) {
        this.status = status;
    }

    // ==================== 数据持久化方法 ====================
    // 这些方法用于将入住记录保存到文件或从文件中读取

    /**
     * 将入住记录转换为文件存储格式
     * 
     * 这个方法将入住记录的所有信息按照特定格式组合成字符串
     * 用于保存到checkin.txt（当前入住）或history.txt（历史记录）文件中
     * 
     * 文件格式：客人ID|客人姓名|房间号|入住日期|退房日期|总金额|状态
     * 示例：G123|张三|101|2025-05-20|2025-05-23|600.0|已入住
     * 
     * 字段说明：
     * - 客人ID：用于关联客人信息
     * - 客人姓名：方便直接显示，无需查询
     * - 房间号：标识住在哪个房间
     * - 入住日期：记录入住时间
     * - 退房日期：记录退房时间（预计或实际）
     * - 总金额：记录费用信息
     * - 状态：区分当前入住和历史记录
     * 
     * @return 格式化的字符串，可直接写入文件
     */
    public String toFileString() {
        // 使用"|"作为分隔符连接所有字段
        // 注意字段的顺序要与fromFileString()方法中的解析顺序一致
        return guestId + "|" + guestName + "|" + roomNumber + "|" + checkInDate + "|" +
                checkOutDate + "|" + totalAmount + "|" + status;
    }

    /**
     * 从文件格式的字符串创建CheckIn对象
     * 
     * 这是一个静态工厂方法，用于从文件中读取数据并创建CheckIn对象
     * 当系统启动时，会读取checkin.txt和history.txt文件，
     * 使用这个方法将每一行数据转换为CheckIn对象
     * 
     * 解析过程：
     * 1. 使用split()方法按"|"分割字符串
     * 2. 检查分割后的数组长度是否正确
     * 3. 将字符串数组的各个元素转换为相应的数据类型
     * 4. 创建并返回CheckIn对象
     * 
     * 错误处理：
     * - 如果字段数量不正确，返回null
     * - 如果数字格式错误，会抛出NumberFormatException异常
     * 
     * @param line 从文件中读取的一行数据
     * @return 创建的CheckIn对象，如果数据格式错误则返回null
     */
    public static CheckIn fromFileString(String line) {
        // 按"|"分割字符串，得到各个字段
        String[] parts = line.split("\\|");

        // 验证字段数量：应该有7个字段
        // 如果字段数量不对，说明数据格式有问题
        if (parts.length == 7) {
            // 解析各个字段：
            // parts[0] = 客人ID（字符串）
            // parts[1] = 客人姓名（字符串）
            // parts[2] = 房间号（字符串）
            // parts[3] = 入住日期（字符串）
            // parts[4] = 退房日期（字符串）
            // parts[5] = 总金额（需要转换为double）
            // parts[6] = 状态（字符串）

            // Double.parseDouble()将字符串转换为double类型
            // 如果字符串不是有效的数字，会抛出NumberFormatException
            return new CheckIn(parts[0], parts[1], parts[2], parts[3],
                    parts[4], Double.parseDouble(parts[5]), parts[6]);
        }

        // 如果数据格式不正确，返回null
        // 调用方需要检查返回值是否为null
        return null;
    }

    /**
     * 重写toString()方法，提供友好的字符串表示
     * 
     * 这个方法定义了当我们打印CheckIn对象时显示的内容
     * 主要用于：
     * 1. 调试时查看对象内容
     * 2. 日志记录
     * 3. 在界面上显示入住记录摘要
     * 
     * 显示格式包含了最重要的信息：
     * - 客人姓名：方便识别是哪位客人
     * - 房间号：知道住在哪个房间
     * - 入住和退房日期：了解入住时间段
     * - 总金额：了解费用情况
     * - 状态：了解当前状态
     * 
     * @return 入住记录的友好显示格式
     */
    @Override
    public String toString() {
        // 返回包含关键信息的字符串
        // 使用中文标签，方便用户理解
        return "客人: " + guestName + ", 房间: " + roomNumber + ", 入住日期: " + checkInDate +
                ", 退房日期: " + checkOutDate + ", 金额: ¥" + totalAmount + ", 状态: " + status;
    }
}